#include"myshell.h"
#include<iostream>
#include<string.h>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<errno.h>

char *gargv[SARGC] = {NULL};//全局命令行参数表
int gargc = 0;
char pwd[1024]={0};//全局变量保存当前工作路径
int lastnode = 0;//保存程序退出码


//0、初始化数据
void InitGlobal()
{
    gargc=0;
    memset(gargv,0,sizeof(gargv));
}

//1、打印命令行提示符
static std::string GetUserName()
{
    std::string user = getenv("USER");
    return user.empty()?"None":user;
}

static std::string GetHostName()
{
    std::string hostname = getenv("HOSTNAME");
    return hostname.empty()?"None":hostname;
}

static std::string GetPwd()
{
//    std::string pwd = getenv("PWD");
//    return pwd.empty()?"None":pwd;
//    shell自己更新pwd环境变量的值  
      char temp[1024]={0};
      getcwd(temp,sizeof(temp));

      snprintf(pwd,sizeof(pwd),"PWD=%s",temp);
      putenv(pwd);
      
      std::string tmp = temp;//变成string类型，方便操作
      const std::string s = "/";
      size_t pos = tmp.rfind(s);
      if(pos==std::string::npos)
      {
        return "None";
      }
      else 
      {
          tmp=tmp.substr(pos+s.size());//从/后面开始截取字符串
      }
      return tmp.empty()?"/":tmp;
}

static std::string GetHomePath()
{
    std::string home = getenv("HOME");
    return home.empty()?"/":home;
}
void PrintCommand()
{
    std::string user = GetUserName();
    std::string hostname = GetHostName();
    std::string pwd = GetPwd();
    printf("[%s@%s %s]#",user.c_str(),hostname.c_str(),pwd.c_str());

}



//2、获取用户输入的命令字符串
bool GetCommandStr(char cmdstr[],int sz)
{
    if(cmdstr==NULL||sz<=0)
        return false;
    char* str = fgets(cmdstr,sz,stdin);
    //debug
    //printf("debug-cmdstr:%s",cmdstr);
    if(str==NULL)
        return false;
    //pwd\n-->pwd\0
    cmdstr[strlen(cmdstr)-1]=0;
    return strlen(cmdstr)?true:false;
}

//3、解析命令字符串
bool ParCommandStr(char cmdstr[])
{
    if(cmdstr==NULL)
        return false;
    //"ls -l -a" --> "ls" "-l" "-a"
#define FL " "
    gargv[gargc++]=strtok(cmdstr,FL);
    while((bool)(gargv[gargc++]=strtok(NULL,FL))){}
    
    gargc--;

//#define Debug 
#ifdef Debug 
    printf("-------------------------------\n");
    printf("gargc:%d\n",gargc);
    printf("-------------------------------\n");
    for(int i=0;i<gargc;i++)
    {
        printf("gargv[%d]:%s\n",i,gargv[i]);
    }
    printf("-------------------------------\n");
    for(int i=0;gargv[i];i++)
    {
        printf("gargv[%d]:%s\n",i,gargv[i]);
    }
#endif
    return true;
}


//4、内建命令，shell进行执行
bool InCommandExec()
{
    std::string cmd = gargv[0];
    bool ret = false;
    if(cmd == "cd")
    {
        if(gargc == 1)
        {
            ret = true;
            chdir(GetHomePath().c_str());
        }
        else if(gargc == 2)
        {
            std::string tmp = gargv[1];
            if(tmp == "~")
            {
                ret = true;
                chdir(GetHomePath().c_str());
            }
            else 
            {
                ret = true;
                chdir(gargv[1]);
            }
        }
        else 
        {
            //命令有问题
        }
    }
    //echo也是内建命令
    else if(cmd == "echo")
    {
        if(gargc==2)
        {
            //等于2是有效的
            const std::string tmp = gargv[1];
            if(tmp[0]=='$')
            {
                if(tmp[1]=='?')
                {
                    printf("lastnode:%d\n",lastnode);
                    ret=true;
                }
                else 
                {
                    const char* name=&tmp[1];  
                    printf("%s\n",getenv(name));
                    lastnode=0;
                    ret=true;
                }
            }
            else 
            {
                printf("%s\n",tmp.c_str());
                lastnode=0;
                ret=true;
            }
        }
    }
    return ret;
}

//5、其他命令，创建子进程执行
void ForkAndExec()
{
    pid_t id = fork();
    if(id==0)
    {
        //子进程
        execvp(gargv[0],gargv);
        exit(0);
    }
    else if(id < 0)
    {
        //出错
        perror("fork");
        return;
    }
    else 
    {
        //父进程
        int status = 0;
        pid_t ret = waitpid(id,&status,0);
        if(ret > 0)
        {
            lastnode = WEXITSTATUS(status);//获取退出码
        }
    }
}



